package data_structs;

import java.io.Serializable;

import util.ModInt;

import errors.IncorrectNucleotide;

public class SequenceWrapper implements Serializable{

	private int hash;
//	private int id;
//	private int position;
	private boolean complement;
	
	private int info;
	
	public SequenceWrapper(String sequence, int position, boolean complement) throws IncorrectNucleotide {
		this("0", sequence, position, complement);
	}
	
	public SequenceWrapper(String id, String sequence, int position, boolean complement) throws IncorrectNucleotide {
//		this.id = Integer.parseInt(id);
//		this.position = position;
		this.complement = complement;
		this.hash = makeHash(sequence.toUpperCase());
		
		//Create binary version of the final int
		info = position << 23;
		info += Integer.parseInt(id);
		
		
//		String binVal = "";
//		binVal = ( complement ) ? "1" : "0";
//		binVal += ModInt.convertToString(Integer.parseInt(id),23);
//		binVal += ModInt.convertToString(position,8);
//		//Integer.parseInt() won't take unsigned binary numbers
//		//Add "-" if the first bit is "1" (if it is a complement)
//		if( complement ) {
//			binVal = ModInt.flipBits(binVal);
//			binVal = "-"+binVal;
//		}
//		info = Integer.parseInt(binVal, 2);
		
	}
	
	private int makeHash(String s) throws IncorrectNucleotide {
		long ret = 0;
		//Iterate through sequence and convert into an integer string
		for(int j = 0, i = s.length()-1; i >= 0; i--, j++) {
			char c = s.charAt(i);
			switch(c) {
				case 'A': ret += Math.pow(8, j); break;
				case 'T': ret += 2 * Math.pow(8, j); break;
				case 'C': ret += 3 * Math.pow(8, j); break;
				case 'G': ret += 4 * Math.pow(8, j); break;
				case 'N': ret += 5 * Math.pow(8, j); break;
				default: throw new IncorrectNucleotide("Nucleotide '" + c + "' is not valid.");
			}
		}
		return (int) ret;
	}
	
	//Accessor methods
	public int getID(){
		return (info << 9) >>> 9;
		
		
//		return id;
//		String binVal = Integer.toString(info, 2);
//		
//		if( isComplement() ) binVal = binVal.substring(1);
//		while( binVal.length() < 32 ) binVal = "0"+binVal;
//		if( isComplement() ) binVal = ModInt.flipBits(binVal);
//		binVal = binVal.substring(1, 24);
//		
//		return Integer.parseInt(binVal, 2);
	}
	
	public int getPosition() {
		return info >>> 23;
		
		
//		return position;
//		String binVal = Integer.toString(info, 2);
//		
//		if( isComplement() ) binVal = binVal.substring(1);
//		while( binVal.length() < 32 ) binVal = "0"+binVal;
//		if( isComplement() ) binVal = ModInt.flipBits(binVal);
//		binVal = binVal.substring(24);
//		
//		return Integer.parseInt(binVal, 2);
	}
	
	public boolean isComplement() {
		return complement;
//		return info < 0;
	}
	
	public int hashCode() {
		return hash;
	}	
}
